﻿#light

open System
open System.Collections.Generic
open System.Runtime.InteropServices
open System.Threading
open Dwarf.Managed
open System.Threading.Tasks

[<DllImport(@"CliTools.dll")>]
extern void start()

[<DllImport(@"CliTools.dll")>]
extern double finish()

[<DllImport(@"CliTools.dll")>]
extern void usage()

let solve(dwarfConfigurator : Configurator) : List<int> =
    let mutable statesVal = null : int[,]                                       // matrix of states  
    let initialPositionVal =  ref 0                                             // constant value to be added to the each result element for a content part
    let patternVal = ref null
    let contentPartCount = dwarfConfigurator.GetData(patternVal, dwarfConfigurator.GetThreadCount())    //evaluating the count of content parts and pattern

    let statesVal = FiniteStateMachineFSharpMethod.constructStates(!patternVal) // state matrix construction
    let positions = new List<int>()                                             // result list storage

    // parallel task begin
    let ParallelTask i =
        let contentVal =  ref null
        lock statesVal (fun() -> contentVal := dwarfConfigurator.GetNextInputPart())  // synchronized inputfile reading

        let contentLengthVal = (!contentVal).Length - (int)(!contentVal).[(!contentVal).Length - 1] - 1
        let fsm : FiniteStateMachineFSharpMethod.fsmType =                      // creation of new fsm instance
            {
                pattern = !patternVal;
                content = !contentVal;
                states = statesVal;
                stateDimensionCoincidence = (!patternVal).Length;
                initialPosition = !initialPositionVal;
                positions = new List<int>();
                contentLength = contentLengthVal
            }
        initialPositionVal := !initialPositionVal + contentLengthVal            // updating of initialPosition (shift)
        FiniteStateMachineFSharpMethod.solve(fsm)                               // solving the problem for the fsm instance

        lock positions (fun() -> positions.AddRange(fsm.positions))             // syncronized updating of result list
    // parallel task end

    Parallel.For(0, contentPartCount, new Action<int>(ParallelTask)) 

    positions.Sort()
    positions       

let main() =
    let args = System.Environment.GetCommandLineArgs()
    let dwarfConfigurator = new Configurator(args)
    dwarfConfigurator.WriteSettings() 
    start()

    let positions = solve(dwarfConfigurator)

    let time = finish()
    Console.WriteLine("Total count of pattern entries: " + (string)positions.Count);
    dwarfConfigurator.Close(time, positions)

main()